package com.jmga.ecogasfinder.activities.gasstation;

import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.location.Location;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.LinearLayout;
import android.widget.TwoLineListItem;

import com.jmga.ecogasfinder.R;
import com.jmga.ecogasfinder.activities.Preferences;
import com.jmga.ecogasfinder.activities.maps.ECOGasStationFinderMapActivity;
import com.jmga.ecogasfinder.providers.GasFinderProvider;
import com.jmga.ecogasfinder.services.LookupGasFinderService;
import com.jmga.ecogasfinder.utilities.Tools;
import com.jmga.ecogasfinder.vo.GasStation;

public class GasStationSummaryActivity extends Activity {

	private static final int LIMIT_SHOWN = 5;
	private static final int MIN_PERIMETER_METERS = 1000;
	private static final int MAX_ATTEMPTS = 10;
	
	public static final String INFLATE_LINEAR_LAYOUT = "INFLATE_LINEAR_LAYOUT";
	public static final String KEY_STATION_LIST = "KEY_STATION_LIST";
	public static final String KEY_LINEAR_LAYOUT = "KEY_LINEAR_LAYOUT";
	
	private GasStationListReceiver gasStationListReceiver;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		Log.d(getClass().getName(), "GasStationSummaryActivity onCreate");
		requestWindowFeature(Window.FEATURE_NO_TITLE);
		super.onCreate(savedInstanceState);		 
		setContentView(R.layout.gasstation_summary);
		
		Context context = getApplicationContext();
		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
		
		int gasType = Integer.parseInt(prefs.getString(Preferences.PREF_GAS_TYPE, "1"));
		LinearLayout cheaperUsualsLl = null, cheaperLl = null;
		
		cheaperUsualsLl = (LinearLayout) findViewById (R.id.cheaperFavouritesLinearLayout);
		cheaperLl = (LinearLayout) findViewById (R.id.cheaperLinearLayout);
		
		GasFinderAndInflaterLookupTask closerGasFinderAndInflaterLookup = new GasFinderAndInflaterLookupTask();

		Object[] parameters = new Object[2];
		parameters[0] = Integer.valueOf(gasType);
		parameters[1] = R.id.closerLinearLayout;
		closerGasFinderAndInflaterLookup.execute(parameters);
		
		GasFinderAndInflaterLookupTask ecoGasFinderAndInflaterLookup = new GasFinderAndInflaterLookupTask();
		parameters = new Object[2];
		parameters[0] = Integer.valueOf(gasType);
		parameters[1] = R.id.ecoLinearLayout;
		ecoGasFinderAndInflaterLookup.execute(parameters);
		
		inflaterLinearLayout(cheaperUsualsLl, getPrices(R.id.cheaperFavouritesLinearLayout, gasType), context);
		inflaterLinearLayout(cheaperLl, getPrices(R.id.cheaperLinearLayout, gasType), context);
	}
	
	public class SummaryStationOnClickListener implements OnClickListener {
		Context context = null;
		String dataStation = null;
		
		public SummaryStationOnClickListener(Context context, String dataStation) {
			this.context = context;
			this.dataStation = dataStation;
		}

		@Override
		public void onClick(View v) {
	  		if(this.dataStation != null && !this.dataStation.isEmpty()){
	  			String[] priceStationData = this.dataStation.split("@");
	            Date date = new Date(Long.parseLong(priceStationData[1]));
	           	float price = 0f;
	           	double priceValue;
	        
		        DecimalFormat df = new DecimalFormat();
		        DecimalFormatSymbols symbols = new DecimalFormatSymbols();
		        symbols.setDecimalSeparator(',');
		        symbols.setGroupingSeparator(' ');
		        df.setDecimalFormatSymbols(symbols);
				
				try {
					priceValue = (Double) df.parse(priceStationData[0]);
				} catch (ParseException e) {
					priceValue = 0d;
					Log.d(getClass().getName(), "Exception caughted " + e.getLocalizedMessage());
				}
				
				price = (float) priceValue;

				Intent intent = new Intent(this.context, GasStationTabsViewActivity.class);
				GasStation gasStation = new GasStation(priceStationData[3], priceStationData[4], priceStationData[5],
						priceStationData[6],	priceStationData[7], priceStationData[8], priceStationData[9], date,
						priceStationData[10],	priceStationData[11], priceStationData[12], priceStationData[13], priceStationData[2], price);
				
				intent.putExtra(GasFinderProvider.KEY_STATION, gasStation);  		
		  		startActivity(intent);	
	  		}		
		}
	}
	
	private void inflaterLinearLayout(LinearLayout linearLayout, List<String> items, Context context) {
		for(int i=0; i < items.size() && i < LIMIT_SHOWN;i++) {
			TwoLineListItem row;
			SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm", Locale.getDefault());

			DecimalFormat df = new DecimalFormat();
	        DecimalFormatSymbols symbols = new DecimalFormatSymbols();
	        symbols.setDecimalSeparator(',');
	        symbols.setGroupingSeparator(' ');
	        df.setDecimalFormatSymbols(symbols);
		       
			LayoutInflater inflater = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            row = (TwoLineListItem) inflater.inflate(android.R.layout.simple_list_item_2, null);                    
        
            SummaryStationOnClickListener summStationOnClickListener = new SummaryStationOnClickListener(context, items.get(i));
            
            String[] priceStationData = items.get(i).split("@");
            Date date = new Date(Long.parseLong(priceStationData[1]));

			double priceValue;
			try {
				priceValue = (Double) df.parse(priceStationData[0]);
			} catch (ParseException e) {
				priceValue = 0d;
				Log.d(getClass().getName(), "Exception caughted " + e.getLocalizedMessage());
			}
            String distance = "";
            if(priceStationData.length > 14) {
            	DecimalFormat dec = new DecimalFormat("###.###");
        		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
        		
        		int gasType = Integer.parseInt(prefs.getString(Preferences.PREF_GAS_TYPE, "1"));
        		float averageConsumption = Float.parseFloat(prefs.getString(Preferences.PREF_AVERAGE_CONSUMPTION, "8"));
        		
            	double co2 = Double.parseDouble(priceStationData[14])*getCo2Emissions(gasType, averageConsumption);
            	distance = "\n" + priceStationData[14] + " km (" + dec.format(co2) + " gr CO2/Km)";
            }
            
            
            row.getText1().setText(priceValue + getString(R.string.euroCurrencyLabel) + distance);
            row.getText2().setText(sdf.format(date) + " " + priceStationData[3] + " " + priceStationData[5] + " " + priceStationData[7] + " " + priceStationData[9]);
            row.setOnClickListener(summStationOnClickListener);
            
            linearLayout.addView(row);
		}
	}

	private double getCo2Emissions(int gasType, float averageConsumption) {
		double fuelEmission = 23.70;
		double dieselEmission = 26.50;
		double result;
		
		ContentResolver cr = getContentResolver();
		String gasTypeWhere = GasFinderProvider.KEY_ID + " = " + gasType;
		Cursor cursor = cr.query(GasFinderProvider.CONTENT_URI_GAS_TYPES, null, gasTypeWhere, null, null);
		GasFinderProvider.GasTypeEnum xkeyGasType = GasFinderProvider.GasTypeEnum.PRICE_95;
		if(cursor.getCount() != 0) {
			cursor.moveToNext();
			xkeyGasType = GasFinderProvider.GasTypeEnum.valueOf(cursor.getString(cursor.getColumnIndexOrThrow(GasFinderProvider.KEY_XKEY)));
		}
		
		switch (xkeyGasType) {
		case PRICE_A:
			result = dieselEmission*averageConsumption;
			break;

		default:
			result = fuelEmission*averageConsumption;
			break;
		}		
		return result;
	}

	private ArrayList<String> getPrices(int mode, int gasType) {
		ArrayList<String> result = new ArrayList<String>();
		HashMap<String, String> stationsDataHashMap = null;
		List<GasStation> stationsList = null;
		String[] stationArgs = new String[1];
		String stations = "";
		
		Cursor pricesCursor = null, stationCursor = null;
		String pricesWhere = null, stationWhere = null;
		String priceOrderAsc = GasFinderProvider.KEY_PRICE + " ASC";
		String dateGroupBy = GasFinderProvider.KEY_STATION;
		String dateHaving = GasFinderProvider.KEY_DATE + " = max(" + GasFinderProvider.KEY_DATE + ")";
		
		ContentProvider cp = getContentResolver().acquireContentProviderClient(GasFinderProvider.CONTENT_URI_PRICES).getLocalContentProvider();
		GasFinderProvider fld = (GasFinderProvider) cp;
		ECOGasStationFinderMapActivity mainActivity = Tools.getInstance().getMapActivity();
		Location myLocation = mainActivity.getMyLocationOverlay();

		switch (mode) {
		case R.id.cheaperFavouritesLinearLayout:
			stationWhere = GasFinderProvider.KEY_FAVOURITE + " = 1";
			stationCursor = getContentResolver().query(GasFinderProvider.CONTENT_URI_STATIONS, null, stationWhere, null, null);
			if(stationCursor.getCount() != 0) {
				stationsDataHashMap = new HashMap<String, String>();
				while(stationCursor.moveToNext()) {
					String stationCoords = String.valueOf(stationCursor.getDouble(stationCursor.getColumnIndex(GasFinderProvider.KEY_X_COORD))) +
						String.valueOf(stationCursor.getDouble(stationCursor.getColumnIndex(GasFinderProvider.KEY_Y_COORD)));
					stations += "'" +  stationCoords + "',";
					stationsDataHashMap.put(stationCoords, getStationDataString(stationCursor));					
				}
			}
			stationCursor.close();
			if(!stations.isEmpty()){
				stationArgs[0] = stations.substring(0, stations.length() - 1);
				pricesWhere = GasFinderProvider.KEY_GAS_TYPE + " = '" + gasType + "' AND " + GasFinderProvider.KEY_STATION + " IN (" + stationArgs[0] + ")";
				pricesCursor = fld.query(GasFinderProvider.CONTENT_URI_PRICES, null, pricesWhere, null, dateGroupBy, dateHaving, 
						priceOrderAsc + " LIMIT " + LIMIT_SHOWN);
				
				if(pricesCursor.getCount() != 0) {
					while(pricesCursor.moveToNext()) {
						String priceValueString = pricesCursor.getString(pricesCursor.getColumnIndex(GasFinderProvider.KEY_PRICE));
						String date = pricesCursor.getString(pricesCursor.getColumnIndex(GasFinderProvider.KEY_DATE));
						String station = pricesCursor.getString(pricesCursor.getColumnIndex(GasFinderProvider.KEY_STATION));
						result.add(priceValueString + "@" + date + "@" + stationsDataHashMap.get(station));
					}
				}
			}
			break;
		case R.id.cheaperLinearLayout:
			String url = getString(R.string.gmaps_reverse_geocode_feed) + myLocation.getLatitude() 
				+ "," + myLocation.getLongitude();
			String locality = Tools.getLocationLocality(Tools.getLocationInfo(url));
			Log.d(getClass().getName(), "LocalityByMyLocation:" + locality);
			stationsList = LookupGasFinderService.lookUpHtmlSynchronous(gasType, getString(R.string.cheapers_by_locality_feed), getString(R.string.gasTypeParam_feed), locality, LIMIT_SHOWN);
			for(GasStation gasStation : stationsList) {
				
				String priceString = null, xkeyString = null, labelString = null, operatorString = null, addressString = null, laneString = null, postalCodeString = null, provinceString = null,
				localityString = null, saleTypeString = null, sentTypeString = null, xCoordString = null, yCoordString = null;
		
				Long dateLong = gasStation.getDate().getTime();
	        
				priceString = String.valueOf(gasStation.getPrice()).replaceAll("\\.", ",");
				xkeyString = gasStation.getXkey();
				labelString = gasStation.getLabel();
				operatorString = gasStation.getOperator();
				addressString = gasStation.getAddress();
				laneString = gasStation.getLane();
				postalCodeString = gasStation.getPostalCode();
				provinceString = gasStation.getProvincie();
				localityString = gasStation.getLocality();
				saleTypeString = gasStation.getSaleType();
				sentTypeString = gasStation.getSentType();
		        xCoordString = gasStation.getXCoord();
		        yCoordString = gasStation.getYCoord();
						        
				String dataStation = priceString + "@" + dateLong + "@" + xkeyString + "@" + labelString + "@" + operatorString + "@" + addressString + "@" + laneString + "@" + postalCodeString + "@" + 
					provinceString + "@" + localityString + "@" + saleTypeString + "@" + sentTypeString + "@" + xCoordString + "@" + yCoordString;
				
				result.add(dataStation);
			}
			break;
		case R.id.ecoLinearLayout:
			stationWhere = GasFinderProvider.KEY_FAVOURITE + " = 1 OR " + GasFinderProvider.KEY_OBSERVABLE + " = 1";
			stationCursor = getContentResolver().query(GasFinderProvider.CONTENT_URI_STATIONS, null, stationWhere, null, null);
			
			if(stationCursor.getCount() != 0) {
				String gmapsFeed = getString(R.string.gmaps_feed);

				while(stationCursor.moveToNext()) {
					String stationCoords = String.valueOf(stationCursor.getDouble(stationCursor.getColumnIndex(GasFinderProvider.KEY_X_COORD))) +
						String.valueOf(stationCursor.getDouble(stationCursor.getColumnIndex(GasFinderProvider.KEY_Y_COORD)));

					Location location = new Location("dummyGPS");
			        location.setLongitude(stationCursor.getDouble(stationCursor.getColumnIndex(GasFinderProvider.KEY_X_COORD)));
			        location.setLatitude(stationCursor.getDouble(stationCursor.getColumnIndex(GasFinderProvider.KEY_Y_COORD)));

			        double dist = Tools.getDistanceDriving(gmapsFeed, myLocation, location);
					
					pricesWhere = GasFinderProvider.KEY_GAS_TYPE + " = '" + gasType + "' AND " + GasFinderProvider.KEY_STATION + " = '" + stationCoords + "'";
					pricesCursor = fld.query(GasFinderProvider.CONTENT_URI_PRICES, null, pricesWhere, null, dateGroupBy, dateHaving, 
							priceOrderAsc + " LIMIT " + LIMIT_SHOWN);
					
					if(pricesCursor.getCount() != 0) {
						while(pricesCursor.moveToNext()) {
							String priceValueString = pricesCursor.getString(pricesCursor.getColumnIndex(GasFinderProvider.KEY_PRICE));
							String date = pricesCursor.getString(pricesCursor.getColumnIndex(GasFinderProvider.KEY_DATE));
							
							int i = 0;
							boolean pushed = false;
							
							while(i < result.size() || i == 0) {
								if(result.isEmpty() || dist <= Double.parseDouble(result.get(i).split("@")[14])){
									result.add(i, priceValueString + "@" + date + "@" + getStationDataString(stationCursor) + "@" + dist);
									pushed = true;
									break;
								}
								i++;
							}
							if(!pushed) {
								result.add(i, priceValueString + "@" + date + "@" + getStationDataString(stationCursor) + "@" + dist);
							}
						}
					}
					pricesCursor.close();
				}
			}
			stationCursor.close();
			break;	
		case R.id.closerLinearLayout:
			int attempts = 1;
			stationsList = new ArrayList<GasStation>();
			
			while(attempts < MAX_ATTEMPTS && stationsList.size() < LIMIT_SHOWN) {
				String perimeterSearch = mainActivity.getRectPerimeterByCoord(myLocation.getLongitude(),
						myLocation.getLatitude(), attempts*MIN_PERIMETER_METERS);
				stationsList = LookupGasFinderService.lookUpSynchronous(gasType, getString(R.string.gas_station_feed), 
						getString(R.string.gasTypeParam_feed), getString(R.string.BBOXParam_feed), perimeterSearch);
				attempts++;
			}
			for(GasStation gasStation : stationsList) {
				
				String priceString = null, xkeyString = null, labelString = null, operatorString = null, addressString = null, laneString = null, postalCodeString = null, provinceString = null,
					localityString = null, saleTypeString = null, sentTypeString = null, xCoordString = null, yCoordString = null;
			
				Long dateLong = gasStation.getDate().getTime();
	        
				priceString = String.valueOf(gasStation.getPrice()).replaceAll("\\.", ",");
				xkeyString = gasStation.getXkey();
				labelString = gasStation.getLabel();
				operatorString = gasStation.getOperator();
				addressString = gasStation.getAddress();
				laneString = gasStation.getLane();
				postalCodeString = gasStation.getPostalCode();
				provinceString = gasStation.getProvincie();
				localityString = gasStation.getLocality();
				saleTypeString = gasStation.getSaleType();
				sentTypeString = gasStation.getSentType();
		        xCoordString = gasStation.getXCoord();
		        yCoordString = gasStation.getYCoord();
		        
				String dataStation = priceString + "@" + dateLong + "@" + xkeyString + "@" + labelString + "@" + operatorString + "@" + addressString + "@" + laneString + "@" + postalCodeString + "@" + 
					provinceString+ "@" + localityString + "@" + saleTypeString + "@" + sentTypeString + "@" + xCoordString + "@" + yCoordString;
				
				
				Location gasStationlocation = new Location("dummyGPS");
				gasStationlocation.setLongitude(Double.parseDouble(gasStation.getXCoord()));
				gasStationlocation.setLatitude(Double.parseDouble(gasStation.getYCoord()));
				
				double dist = Tools.getDistanceDriving(getString(R.string.gmaps_feed), mainActivity.getMyLocationOverlay(), gasStationlocation);
				dataStation += "@" + dist;
				
				int i = 0;
				boolean pushed = false;
				
				while(i < result.size() || i == 0) {
					if(result.isEmpty() || dist <= Double.parseDouble(result.get(i).split("@")[14])){
						result.add(i, dataStation);
						pushed = true;
						break;
					}
					i++;
				}
				if(!pushed) {
					result.add(i, dataStation);
				}				
			}
			break;

		default:
			break;
		}
		
		return result;
	}

	private String getStationDataString(Cursor cursor) {
		String result = null;
		
		String xkeyString = null, labelString = null, operatorString = null, addressString = null, laneString = null, postalCodeString = null, provinceString = null,
		localityString = null, saleTypeString = null, sentTypeString = null, xCoordString = null, yCoordString = null;
    
		xkeyString = cursor.getString(cursor.getColumnIndexOrThrow(GasFinderProvider.KEY_XKEY));
		labelString = cursor.getString(cursor.getColumnIndexOrThrow(GasFinderProvider.KEY_LABEL));
		operatorString = cursor.getString(cursor.getColumnIndexOrThrow(GasFinderProvider.KEY_OPERATOR));
		addressString = cursor.getString(cursor.getColumnIndexOrThrow(GasFinderProvider.KEY_ADDRESS));
		laneString = cursor.getString(cursor.getColumnIndexOrThrow(GasFinderProvider.KEY_LANE));
		postalCodeString = cursor.getString(cursor.getColumnIndexOrThrow(GasFinderProvider.KEY_POSTAL_CODE));
		provinceString = cursor.getString(cursor.getColumnIndexOrThrow(GasFinderProvider.KEY_PROVINCE));
		localityString = cursor.getString(cursor.getColumnIndexOrThrow(GasFinderProvider.KEY_LOCALITY));
		saleTypeString = cursor.getString(cursor.getColumnIndexOrThrow(GasFinderProvider.KEY_SALE_TYPE));
		sentTypeString = cursor.getString(cursor.getColumnIndexOrThrow(GasFinderProvider.KEY_SENT_TYPE));
        double xCoord = cursor.getDouble(cursor.getColumnIndexOrThrow(GasFinderProvider.KEY_X_COORD));
        double yCoord = cursor.getDouble(cursor.getColumnIndexOrThrow(GasFinderProvider.KEY_Y_COORD));
        xCoordString = String.valueOf(xCoord);
        yCoordString = String.valueOf(yCoord);
    
		result = xkeyString + "@" + labelString + "@" + operatorString + "@" + addressString + "@" + laneString + "@" + postalCodeString + "@" + 
			provinceString+ "@" + localityString + "@" + saleTypeString + "@" + sentTypeString + "@" + xCoordString + "@" + yCoordString;
		
		return result;
	}

	@Override
	protected void onDestroy() {
		Log.d(getClass().getName(), "GasStationSummaryActivity super.onDestroy()");
		super.onDestroy();
		
	}

	@Override
	protected void onPause() {
		Log.d(getClass().getName(), "GasStationSummaryActivity super.onPause()");
		unregisterReceiver(gasStationListReceiver);
		super.onPause();
	}

	@Override
	protected void onRestart() {
		Log.d(getClass().getName(), "GasStationSummaryActivity super.onRestart()");
		super.onRestart();
	}

	@Override
	protected void onResume() {
		Log.d(getClass().getName(), "GasStationSummaryActivity super.onResume()");
		
		IntentFilter filter;
    	filter = new IntentFilter(GasStationSummaryActivity.INFLATE_LINEAR_LAYOUT);
    	gasStationListReceiver = new GasStationListReceiver();
    	registerReceiver(gasStationListReceiver, filter);
		super.onResume();
	}

	@Override
	protected void onStart() {
		Log.d(getClass().getName(), "GasStationSummaryActivity super.onStart()");
		super.onStart();
	}

	@Override
	protected void onStop() {
		Log.d(getClass().getName(), "GasStationSummaryActivity super.onStop()");
		super.onStop();
	}

	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState) {
		Log.d(getClass().getName(), "GasStationSummaryActivity super.onRestoreInstanceState()");
		super.onRestoreInstanceState(savedInstanceState);
	}
	
    public class GasStationListReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if(intent != null && intent.getAction() != null && 
            		intent.getAction().equals(GasStationSummaryActivity.INFLATE_LINEAR_LAYOUT)) {
            	List<String> stationsList = intent.getStringArrayListExtra(GasStationSummaryActivity.KEY_STATION_LIST);
            	int idLayout = intent.getIntExtra(GasStationSummaryActivity.KEY_LINEAR_LAYOUT, -1);
            	if(stationsList != null && !stationsList.isEmpty() && idLayout != -1) {
            		LinearLayout linearLayout = (LinearLayout) findViewById (idLayout);
            		inflaterLinearLayout(linearLayout, stationsList, context);
            	}
            }
        }
    }

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		Log.d(getClass().getName(), "GasStationSummaryActivity super.onRestoreInstanceState()");
		super.onSaveInstanceState(outState);
	}
	
	private class GasFinderAndInflaterLookupTask extends AsyncTask<Object, Void, ArrayList<String>> {
		Integer idLayout = null;
		@Override
		protected ArrayList<String> doInBackground(Object... params) {
			int gasType = (Integer) params[0];
			idLayout = (Integer) params[1];			
			
			return getPrices(idLayout, gasType);
	    }
		

		@Override
	    protected void onProgressUpdate(Void... param) {

	    }
	
	    @Override
	    protected void onPostExecute(ArrayList<String> list) {
			Intent intent = new Intent(GasStationSummaryActivity.INFLATE_LINEAR_LAYOUT);
			intent.putStringArrayListExtra(GasStationSummaryActivity.KEY_STATION_LIST, list);
			intent.putExtra(GasStationSummaryActivity.KEY_LINEAR_LAYOUT, idLayout);
			sendBroadcast(intent);
			idLayout = null;
	    }
	}

}